/**
 * Copyright (c) 2016-2019 人人开源 All rights reserved.
 *
 * https://www.renren.io
 *
 * 版权所有，侵权必究！
 */

package com.theme.passport.controller.oss.cloud;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.*;
import com.theme.common.mvc.exception.RRException;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;

/**
 * 阿里云存储
 *
 * @author Mark sunlightcs@gmail.com
 */
public class AliyunCloudStorageService extends CloudStorageService {

    private static final Logger logger = LoggerFactory.getLogger(CloudStorageService.class);

    private OSSClient client;

    public AliyunCloudStorageService(CloudStorageConfig config){
        this.config = config;
        //初始化
        init();
    }

    private void init(){
        client = new OSSClient(config.getAliyunEndPoint(), config.getAliyunAccessKeyId(),
                config.getAliyunAccessKeySecret());
    }

    @Override
    public String upload(byte[] data, String path) {
        return upload(new ByteArrayInputStream(data), path);
    }

    @Override
    public String upload(InputStream inputStream, String path) {
        try {
            client.putObject(config.getAliyunBucketName(), path, inputStream);
        } catch (Exception e){
            throw new RRException("上传文件失败，请检查配置信息", e);
        }

        return config.getAliyunDomain() + "/" + path;
    }

    @Override
    public String uploadSuffix(byte[] data, String suffix) {
        if (config.getAliyunFileName() != null){
            String fileName = config.getAliyunFileName();
            String directorName = config.getAliyunDirName();
            String prefix = config.getAliyunPrefix();
            //文件路径
            String path = directorName + "/" + fileName;
            if(StringUtils.isNotBlank(prefix)){
                path = prefix + "/" + path;
            }
            String FilePath = path + suffix;
            return upload(data, FilePath);
        }
        return upload(data, getPath(config.getAliyunPrefix(), suffix));
    }

    @Override
    public String uploadSuffix(InputStream inputStream, String suffix) {
        return upload(inputStream, getPath(config.getAliyunPrefix(), suffix));
    }

    @Override
    public String getFilePath(String httpUrl) {
        String aliyunDomain = config.getAliyunDomain();
        return httpUrl.replaceAll(aliyunDomain,"");
    }

    @Override
    public List<String> getFileList(String dirName,String suffix) {
        ListObjectsRequest listObjectsRequest = new ListObjectsRequest(config.getAliyunBucketName());
        listObjectsRequest.setPrefix(dirName); //指定下一级文件
        listObjectsRequest.setMarker("maker");  //获取下一页的起始点，它的下一项
        listObjectsRequest.setMaxKeys(100);//设置分页的页容量
        listObjectsRequest.setDelimiter("/");;//跳出递归循环，只去指定目录下的文件。使用它时 Prefix文件路径要以“/”结尾
        ObjectListing result = client.listObjects(listObjectsRequest);
        List<OSSObjectSummary> objectSummaries = result.getObjectSummaries();
        List<String> objects = new ArrayList<>();
        String aliyunDomain = config.getAliyunDomain();
        objectSummaries.forEach(object ->{
            //判断是否是文件 如.zip 还是.jpg 格式添加
            String fileName = object.getKey();
            if (!fileName.equals(dirName)){
                String  httpFile = aliyunDomain + fileName;
                objects.add(httpFile);
            }
        });
        return objects;
    }

    /**
     * OSS删除单个文件 test/111.jpg
     * @param key 文件路径(不包含域名)
     */
    @Override
    public boolean deleteObject(String key) {
        try {
            client.deleteObject(config.getAliyunBucketName(), key);
            // 关闭OSSClient。
            //client.shutdown();
        } catch (Exception e){
            throw new RRException("删除文件失败，请检查配置信息", e);
        }
        return true;
    }

    /**
     * OSS删除指定的多个文件
     * @param keys 文件路径 不包含域名
     */
    @Override
    public boolean deleteObjectKeys(List<String> keys) {
        DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(config.getAliyunBucketName()).withKeys(keys);
        //deleteObjectsRequest.withEncodingType(URL_ENCODING);
        DeleteObjectsResult deleteObjectsResult = client.deleteObjects(deleteObjectsRequest);
        List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
        try {
            for(String obj : deletedObjects) {
                String deleteObj =  URLDecoder.decode(obj, "UTF-8");
                //logger.info("删除阿里云文件:{}",deleteObj);
            }
        } catch (Exception e){
            throw new RRException("删除多个文件失败，请检查配置信息", e);
        }
        // 关闭OSSClient。
        //client.shutdown();
        return true;
    }

    /**
     * OSS删除指定目录及目录下的所有文件
     * @param prefix 文件目录 例如Bucket下testdir目录的完整路径为testdir/
     */
    @Override
    public boolean deleteObjectDir(String prefix) {
        // 删除目录及目录下的所有文件。
        String nextMarker = null;
        ObjectListing objectListing = null;
        do {
            ListObjectsRequest listObjectsRequest = new ListObjectsRequest(config.getAliyunBucketName())
                    .withPrefix(prefix)
                    .withMarker(nextMarker);

            objectListing = client.listObjects(listObjectsRequest);
            if (objectListing.getObjectSummaries().size() > 0) {
                List<String> keys = new ArrayList<String>();
                for (OSSObjectSummary s : objectListing.getObjectSummaries()) {
                    //System.out.println("key name: " + s.getKey());
                    logger.info("删除阿里云OSS目录以及下面的文件key name:{}",s.getKey());
                    keys.add(s.getKey());
                }
                DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(config.getAliyunBucketName()).withKeys(keys);
                //deleteObjectsRequest.withEncodingType(URL_ENCODING);
                DeleteObjectsResult deleteObjectsResult = client.deleteObjects(deleteObjectsRequest);
                List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
                try {
                    for(String obj : deletedObjects) {
                        String deleteObj =  URLDecoder.decode(obj, "UTF-8");
                        //System.out.println(deleteObj);
                        //logger.info("删除阿里云OSS下面的文件key name:{}",deleteObj);
                    }
                }  catch (Exception e){
                    throw new RRException("删除文件夹失败，请检查配置信息", e);
                }
            }
            nextMarker = objectListing.getNextMarker();
        } while (objectListing.isTruncated());

        // 关闭OSSClient。
        // client.shutdown();
        return true;
    }
}
